﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using DataAssociations.AssociationMiningAlgorithms.Facades;
using DataAssociations.Repository.Connection.RDBMSSchemaExplorer;
using DataAssociations.Repository.Connection.RDBMSSchemaExplorer.Interfaces;
using System.Data.Common;
using DataAssociations.Repository.Connection.RDBMSConnectionInterfaces;

namespace DataAssociations
{
    public static class AlgorithmInputBuilder
    {
        public static IEnumerable<List<string>> BuildInputFor(IConnectionStringType databaseConnection, string tableName, string parentKey, string childKey)
        {
            string query = string.Format("Select {0},{1} FROM [{2}] Order By {0}", parentKey,
                                         childKey,
                                         tableName);
            using (var connection = databaseConnection.DataConnection)
            {
                connection.Open();
                var cmd = databaseConnection.GetDbCommand(query);
                using (var reader = databaseConnection.DataReader)
                {
                    string transactionId = "";
                    string previousId = "";
                    var transactionItems = new List<string>();
                    while (reader.Read())
                    {
                        string id = reader[1].ToString();
                        transactionId = reader[0].ToString();
                        if ((transactionItems.Count == 0) || (previousId == transactionId))
                        {
                            transactionItems.Add(id);
                        }
                        else
                        {
                            yield return transactionItems;
                            transactionItems = new List<string> { id };
                        }
                        previousId = transactionId;
                    }
                    yield return transactionItems;
                }
            }
        }
    }

    public class AlgorithmRunner
    {
        private readonly Func<string, IAssociationFinder> _associationInitializer;
        private readonly IConnectionStringType _databaseConnection;
        private readonly IRelationalSchemaExplorer _schemaExporter;
        private IAssociationFinder _associationFinder;
        private Repository.Queries.IDataRepository _dataRepository;

        public AlgorithmRunner(IConnectionStringType connectionType, IRelationalSchemaExplorer schemaExporter, Repository.Queries.IDataRepository dataRepository)
        {
            _databaseConnection = connectionType;
            _schemaExporter = schemaExporter;
            _dataRepository = dataRepository;
            _associationInitializer = x =>
                                          {
                                              x = x.ToLower();
                                              if (x.Contains("fpg"))
                                                  return new FpGrowthAlgorithmRunner();
                                              return new AprioriAlgorithmRunner();
                                          };
        }

        public void Run(RunOptions options)
        {
            _associationFinder = _associationInitializer(options.ComboBoxAlgorithm);
            IEnumerable<List<string>> algorithmInput = AlgorithmInputBuilder.BuildInputFor(
                                                            _databaseConnection,
                                                            options.DatabaseMetadata.TableName,
                                                            options.DatabaseMetadata.TransactionColumnName,
                                                            options.DatabaseMetadata.TransactionItemColumnName);

            _associationFinder.FindAssociations(algorithmInput.ToList(), options.TextBoxPath, options.TextBoxSupport,
                                                options.TextBoxConfidence, true);
        }
    }
}
